﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MMK.PaketTracker.Server.Database;
using MMK.PaketTracker.Server.Definitions;
using System.Drawing;
using System.Net;
using System.IO;
using MMK.PaketTracker.Server.Helpers;
using System.Drawing.Imaging;

namespace MMK.PaketTracker.Server.Application
{
    public static class PaketManager
    {
        public static string CreateNewPaket(Adresse absender, Adresse empfaenger, double gewicht, double preis, string paketIdent)
        {
            Paket paket = new Paket();
            if (paketIdent == String.Empty)
            {
                paket.Ident = GeneratePaketIdent();
            }
            else
            {
                paket.Ident = paketIdent;
            }
            paket.Absender = absender;
            paket.Empfaenger = empfaenger;
            paket.Gewicht = gewicht;
            paket.Preis = preis;

            using(AdressenSqlDataLayer db = CreateAdressenSqlDataLayer())
            {
                db.CreateNewAdresse(paket.Ident, paket.Absender, AdresseType.Absender);
                db.CreateNewAdresse(paket.Ident, paket.Empfaenger, AdresseType.Empfaenger);
            }

            using(PaketSqlDataLayer db = CreatePaketSqlDataLayer())
            {
                db.CreateNewPaket(paket);
            }

            return paket.Ident;
        }

        public static void CreateNewPaketStatus(string paketIdent, PaketStatusType status, string statusBeschreibung, Guid mitarbeiterID, Guid stationID)
        {
            using(PaketStatusSqlDataLayer db = CreatePaketStatusSqlDataLayer())
            {
                db.CreateNewPaketStatus(paketIdent, status, statusBeschreibung, mitarbeiterID, stationID);
            }
        }

        public static List<PaketStatus> GetAllPaketStatus(string paketIdent)
        {
            using (PaketStatusSqlDataLayer db = CreatePaketStatusSqlDataLayer())
            {
                using (AdressenSqlDataLayer adrdb = CreateAdressenSqlDataLayer())
                {
                    List<PaketStatus> list = db.GetAllPaketStatus(paketIdent);

                    foreach (PaketStatus status in list)
                    {
                        if (status.Status == PaketStatusType.InAuslieferung)
                        {
                            GPSCoordinate fahrzeugpos = db.GetFahrzeugPosition(paketIdent);

                            if (fahrzeugpos != null)
                            {
                                status.Coordinate = fahrzeugpos;
                                status.Zeitstempel = fahrzeugpos.Zeitstempel;
                            }
                        }

                        if (status.Status == PaketStatusType.Ausgeliefert)
                        {
                            Adresse empfaenger = adrdb.LoadAdresse(paketIdent, AdresseType.Empfaenger);
                            status.MapImage = GetGoogleMapsImage(empfaenger);
                        }

                        if (status.StationID != Guid.Empty)
                        {
                            Station station = StationManager.LoadStation(status.StationID);

                            if (station != null)
                            {
                                status.Coordinate = station.Coordinate;
                            }
                        }

                        if (status.Coordinate != null)
                        {
                            status.MapImage = GetGoogleMapsImage(status.Coordinate.Latitude, status.Coordinate.Longitude);
                        }
                    }

                    return list;
                }
            }
        }

        public static PaketStatus GetPaketStatus(string paketIdent)
        {
            using (PaketStatusSqlDataLayer db = CreatePaketStatusSqlDataLayer())
            {
				using (AdressenSqlDataLayer adrdb = CreateAdressenSqlDataLayer())
				{
					PaketStatus status = db.GetLastPaketStatus(paketIdent);

					if (status != null)
					{
						if (status.Status == PaketStatusType.InAuslieferung)
						{
							GPSCoordinate fahrzeugpos = db.GetFahrzeugPosition(paketIdent);

							if (fahrzeugpos != null)
							{
								status.Coordinate = fahrzeugpos;
								status.Zeitstempel = fahrzeugpos.Zeitstempel;
							}
						}

						if (status.Status == PaketStatusType.Ausgeliefert)
						{
							Adresse empfaenger = adrdb.LoadAdresse(paketIdent, AdresseType.Empfaenger);
							status.MapImage = GetGoogleMapsImage(empfaenger);
                            status.MapImageUrl = GetGoogleMapsImageUrl(empfaenger);
						}

						if (status.StationID != Guid.Empty)
						{
							Station station = StationManager.LoadStation(status.StationID);

							if (station != null)
							{
								status.Coordinate = station.Coordinate;
							}
						}

						if (status.Coordinate != null)
						{
							status.MapImage = GetGoogleMapsImage(status.Coordinate.Latitude, status.Coordinate.Longitude);
                            status.MapImageUrl = GetGoogleMapsImageUrl(status.Coordinate.Latitude, status.Coordinate.Longitude);
                        }

						return status;
					}

				}
            
			}

            return null;
		}

        private static string GetGoogleMapsImageUrl(double latitude, double longitude)
        {
            string requestUrl = String.Format("https://maps.googleapis.com/maps/api/staticmap?center={0},{1}&zoom=14&size=400x400&sensor=false&markers=color:red|label:Position|{0},{1}",
              CommonHelper.GetLocationString(latitude),
              CommonHelper.GetLocationString(longitude));

            return requestUrl;

        }
        private static byte[] GetGoogleMapsImage(double latitude, double longitude)
        {
            byte[] imageData;
            
            /*string requestUrl = String.Format("https://maps.googleapis.com/maps/api/staticmap?center={0},{1}&zoom=14&size=400x400&sensor=false&markers=color:red|label:Position|{0},{1}",
                CommonHelper.GetLocationString(latitude),
                CommonHelper.GetLocationString(longitude));
            */
            string requestUrl = GetGoogleMapsImageUrl(latitude, longitude);
            Uri uri = new Uri(requestUrl);

            HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(uri);

            using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse())
            {
                Stream imageStream = httpResponse.GetResponseStream();
                Bitmap image = new Bitmap(imageStream);
                httpResponse.Close();
                imageStream.Close();

                using (MemoryStream m = new MemoryStream())
                {
                    image.Save(m, ImageFormat.Png);
                    imageData = m.ToArray();
                }


                return imageData;
            }
        }

        public static string GetGoogleMapsImageUrl(Adresse adresse)
        {
            string requestUrl = String.Format("https://maps.googleapis.com/maps/api/staticmap?center={0}&zoom=14&size=400x400&sensor=false&markers=color:green|label:Position|{0}",
                adresse.PLZ + " " + adresse.Ort + ",Germany," + adresse.Strasse + " " + adresse.Hausnummer);


            return requestUrl;
        }

		public static byte[] GetGoogleMapsImage(Adresse adresse)
		{
			byte[] imageData;

			//string requestUrl = String.Format("https://maps.googleapis.com/maps/api/staticmap?center={0}&zoom=14&size=400x400&sensor=false&markers=color:green|label:Position|{0}",
				//adresse.PLZ + " " + adresse.Ort + ",Germany," + adresse.Strasse + " " + adresse.Hausnummer);

            string requestUrl = GetGoogleMapsImageUrl(adresse);

			Uri uri = new Uri(requestUrl);

			HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(uri);

			using (HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse())
			{
				Stream imageStream = httpResponse.GetResponseStream();
				Bitmap image = new Bitmap(imageStream);
				httpResponse.Close();
				imageStream.Close();

				using (MemoryStream m = new MemoryStream())
				{
					image.Save(m, ImageFormat.Png);
					imageData = m.ToArray();
				}


				return imageData;
			}
		}

        private static string GeneratePaketIdent()
        {
            string ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";    
            string NUMERIC = "0123456789";    
            string ALPHA_NUMERIC = ALPHA + NUMERIC;
            int length = 15;
            string characterSet = ALPHA_NUMERIC;
            
            string randomData = "";
            int position = 0;
            byte[] data = new byte[length];
            int characterSetLength = characterSet.Length;
            System.Security.Cryptography.RandomNumberGenerator random = System.Security.Cryptography.RandomNumberGenerator.Create();
            random.GetBytes(data);
            for (int index = 0; (index < length); index++)
            {
                position = data[index];
                position = (position % characterSetLength);
                randomData = (randomData + characterSet.Substring(position, 1));
            }

            return randomData;
        }

		public static Adresse GetAdresse(string paketIdent, AdresseType type)
		{
			using(AdressenSqlDataLayer db = CreateAdressenSqlDataLayer())
			{
				return db.LoadAdresse(paketIdent, type);
			}
		}
        
        private static PaketSqlDataLayer CreatePaketSqlDataLayer()
        {
            return new PaketSqlDataLayer(Config.DbConnectionString);
        }

        private static AdressenSqlDataLayer CreateAdressenSqlDataLayer()
        {
            return new AdressenSqlDataLayer(Config.DbConnectionString);
        }

        private static PaketStatusSqlDataLayer CreatePaketStatusSqlDataLayer()
        {
            return new PaketStatusSqlDataLayer(Config.DbConnectionString);
        }
	}
}
